package com.my.study.atomic;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * @author Carlos
 * @version 1.0
 * @Description 累加器
 *
 * @sun.misc.Contended用于防止缓存行伪共享
 *
 *
 *
 * @date 2021/6/1 8:06
 **/
@Slf4j(topic = "c.StripedTest")
public class StripedTest {
    private static AtomicInteger val = new AtomicInteger();
    private static final int INCREMENT = 0x9e3779b9;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

//        demo(
//                () -> new AtomicInteger(0),
//                AtomicInteger::getAndIncrement
//        );

//        demo(
//                () -> new LongAdder(),
//                adder -> adder.increment()
//        );

        System.out.println(addAndGet());

    }

    private static <T> void demo(Supplier<T> adderSupplier, Consumer<T> action) {
        T adder = adderSupplier.get();
        List<Thread> ts = new ArrayList<>();
        // 4个线程，每个线程累加50万次
        for (int i = 0; i < 4; i++) {
            ts.add(new Thread(() -> {
                for (int j = 0; j < 500000; j++) {
                    action.accept(adder);
                }
            }));
        }
        long start = System.nanoTime();
        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        long end = System.nanoTime();
        log.debug("{} cost: {}", adder, (end - start) / 100000);
    }


    private void moldTake() {
        int a = 5;
        int b = 2;
        /*
            但b的值为2的幂次方时，a & (b - 1) == a % b
         */
        System.out.println(a & (b - 1));
        System.out.println(a % b);

    }

    private static int addAndGet() {
        return val.addAndGet(INCREMENT);
    }

}
